package NG::Sys::Cached::Common::Parent;
use strict;
use warnings;
use utf8;

# создает экземпля-фабрику
# прверяет наличие приложения, наймспейс
# создает кэш, подключает компрессию
sub new {
	my $class = shift;
	my %arg;
	if(ref $_[0]){
		%arg = %{$_[0]};
	}elsif(@_ % 2){
		die "odd number params\n";
	}else{
		%arg = @_;
	}
	unless($arg{app}){
		die "need app\n";
	}
	unless($arg{namespace}){
		die "need namespace\n";
	}
	my $orig_cache;
	unless(defined ($orig_cache = $arg{cache})){
		die "need cache\n";
	}elsif(!$orig_cache){
		$arg{cache} = $arg{app}->get_cache("nocache",{namespace => $arg{namespace}});
	}elsif(! ref $orig_cache){
		$arg{cache} = $arg{app}->get_cache($orig_cache,{namespace => $arg{namespace}});
	}elsif(UNIVERSAL::isa($orig_cache,"NG::Sys::Cache::Base")){
		$arg{cache} = $orig_cache->clone($arg{namespace});
	}elsif(UNIVERSAL::isa($orig_cache,"HASH")){
		$arg{cache} = $arg{app}->get_cache(%$orig_cache);
	}else{
		die "bad cache specification\n";
	}

	my $self = bless \%arg, $class;

	if($self->{compress}){
		require Compress::Zlib;
	}

	$self->init;
	return $self;
}
sub init {
}
sub make_subclass {
	my ($self,$class,$add) = @_;
	my $nc = "tmp".int($self).($add||"");

	unless(ref $class){
		$class = [$class];
	}
	my $class_list = join " ", @$class;

	my $pack = <<"ECD";
package $nc;
our \@ISA = qw($class_list);
our \$VERSION = 1.0;
ECD
	eval $pack;
	if($@){
		die $@;
	}
	for my $c(@$class){
		if(my $ref = $c->can("configure")){
			$ref->($self,$nc);
		}
	}
	return $nc;
}
sub count_action {
	my ($self,$action) = @_;
	my $context = $self->{app}->get_context("counter");
	($context->{ $self->{namespace} }{$action} ||= 0 )++;
}
sub get_count_action {
	my ($self,$action) = @_;
	my $context = $self->{app}->get_context("counter");
	return $context->{ $self->{namespace} }{$action} ||= 0;
}
sub context {
	my ($self) = @_;
	return $self->{app}->get_context(int $self);
}
sub cache {
	my ($self) = @_;
	return $self->{cache};
}
sub drop_context {
	my ($self,$id) = @_;
	my $c = $self->context;
	$self->count_action("drop");
	delete $c->{$id};
}
sub clear_cache {
	my ($self,$id) = @_;
	my $c = $self->context;
	delete $c->{$id};
	$self->count_action("clear");
	$self->{cache}->remove($id);
}

package NG::Sys::Cached::Common::Child;
use strict;
use warnings;
use utf8;

sub drop_context {
	my ($self) = @_;
	$self->{parent}->drop_context($self->{id});
}
sub clear_cache {
	my ($self) = @_;
	$self->{parent}->clear_cache($self->{id});
}
sub set_cache {
	my ($self,$key,@rest) = @_;
	return $self->{parent}{cache}->set($self->{id}.":".$key,@rest);
}
sub get_cache {
	my ($self,$key,@rest) = @_;
	return $self->{parent}{cache}->get($self->{id}.":".$key,@rest);
}
sub remove_cache {
	my ($self,$key,@rest) = @_;
	return $self->{parent}{cache}->remove($self->{id}.":".$key,@rest);
}
sub DESTROY {}
1;
